/*
 * Copyright 2010 Aekold Helbrass
 * 
 * This file is part of RosterComposer.
 * 
 * RosterComposer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * RosterComposer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with RosterComposer.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.heresylabs.rostercomposer.formatter;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import org.heresylabs.rostercomposer.roster.RosterEntry;
import org.heresylabs.rostercomposer.units.Option;

/**
 *
 * @author Aekold Helbrass <Helbrass@gmail.com>
 */
abstract public class AbstractFormatter implements Formatter {

    final protected List<RosterEntry> roster;
    final protected int totalCost;
    final protected int mostExpensiveLength;
    protected PrintWriter writer;
    protected boolean printTotal = true;

    public AbstractFormatter(List<RosterEntry> roster) {
        this.roster = roster;

        int c = 0;
        int m = 0;
        for (int i = 0; i < roster.size(); i++) {
            RosterEntry rosterEntry = roster.get(i);
            c += rosterEntry.getCost();
            m = Math.max(m, rosterEntry.getCost());
        }
        totalCost = c;
        mostExpensiveLength = String.valueOf(m).length();
    }

    @Override
    final public void write(PrintWriter writer) {
        this.writer = writer;
        for (int i = 0; i < roster.size(); i++) {
            RosterEntry rosterEntry = roster.get(i);
            printEntry(rosterEntry);
        }
        if (printTotal) {
            printTotal(totalCost);
        }
        writer.flush();
    }

    final List<OptionDescription> entryOptions(RosterEntry entry) {
        List<Option> unitOptions = entry.getUnit().getOptions();
        if (unitOptions == null || unitOptions.isEmpty()) {
            return null;
        }
        List<OptionDescription> list = new ArrayList<OptionDescription>();
        for (int i = 0; i < unitOptions.size(); i++) {
            Option option = unitOptions.get(i);
            loadOptionsRecuresively(list, entry, option);
        }
        return list;
    }

    private void loadOptionsRecuresively(List<OptionDescription> list, RosterEntry entry, Option option) {
        if (!entry.hasOption(option)) {
            return;
        }
        if (option.isLeaf()) {
            int c = entry.getOptionsCount(option);
            if (c > 0) {
                OptionDescription description = new OptionDescription(option.getName(), option.getShortName(), c);
                list.add(description);
            }
            return;
        }
        // if we are still here - it's not a leaf
        // we should not add category roots if they are free
        if (option.getCost() > 0) {
            OptionDescription description = new OptionDescription(option.getName(), option.getShortName(), entry.getOptionsCount(option));
            list.add(description);
        }
        List<Option> options = option.getOptions();
        for (int i = 0; i < options.size(); i++) {
            loadOptionsRecuresively(list, entry, options.get(i));
        }
    }

    abstract protected void printEntry(RosterEntry entry);

    protected void printTotal(int total) {
        writer.println();
        writer.println("=============");
        writer.print("        TOTAL: ");
        writer.println(total);
    }

    public boolean isPrintTotal() {
        return printTotal;
    }

    public void setPrintTotal(boolean printTotal) {
        this.printTotal = printTotal;
    }

    protected class OptionDescription {

        final private String name;
        final private String shortName;
        final private int count;

        public OptionDescription(String name, String shortName, int count) {
            this.name = name;
            this.shortName = shortName;
            this.count = count;
        }

        public int getCount() {
            return count;
        }

        public String getName() {
            return name;
        }

        public String getShortName() {
            return shortName;
        }

        public boolean isFree() {
            return count < 1;
        }

    }

}
